from datetime import datetime

import peewee

from emi.bar.storage.model import BaseDBModel


class BarDataModel(BaseDBModel):
    """

        code|int|个股代码
        market_code|int|code所属交易商代码
        yy_mm_dd|int|年月日值，对应当地交易市场的本地时间
        hh_mm|int|小时分钟值
        interval|int|行情频率
        token|int|更新token，-1时表示不再更新,越大表示越新
        open|float|开盘价
        low|float|最低价
        high|float|当前价格
        close|float|当前价格
        pre_close|float|昨日开盘价
        volume|int|成交量，注意单位不是手数
        amount|float|成交金额
        extra|bytes|其他数据
    """

    code: str = peewee.CharField(max_length=64,index=True)
    market_code:int = peewee.SmallIntegerField()
    yy_mm_dd:int = peewee.IntegerField(index=True)
    hh_mm:int = peewee.SmallIntegerField(index=True)
    interval:int = peewee.SmallIntegerField(index=True)
    token:int = peewee.IntegerField()

    open: float = peewee.FloatField()
    low: float = peewee.FloatField()
    high: float = peewee.FloatField()
    close: float = peewee.FloatField()
    pre_close: float = peewee.FloatField()

    volume:int = peewee.BigIntegerField()
    amount: float = peewee.DoubleField()

    extra: bytes = peewee.BlobField(null=True)


    def __str__(self):
        return f"BarDataModel[code:{self.code},market_code:{self.market_code}" \
                f",yy_mm_dd:{self.yy_mm_dd}" \
                f",hh_mm:{self.hh_mm}" \
                f",token:{self.token}" \
               f",close:{self.close}" \
               f",open:{self.open}" \
               f",high:{self.high}" \
               f",low:{self.low}" \
               f",pre_close:{self.pre_close}" \
               f",volume:{self.volume}" \
               f",amount:{self.amount}" \
               f"]"


class TickShotModel(BaseDBModel):
    """
code|text|个股代码
market|int|code所属市场
yy_mm_dd|int|年月日值，对应当地交易市场的本地时间
hh_mm|smallint|所属交易时间段的小时分钟值（与市场相关），构成同一个bar的关键。
group|smallint|分组，用于分批加载数据。
time|datetime|更新时间
source|int|行情采集来源
close|float|当前价格
open|float|当天开盘价
high|float|当天最高价
low|float|当天低价
pre_close|float|昨日收盘价
volume|int|成交量，注意单位不是手数
amount|float|成交金额
level_data|bytes| 档位行情数据块
extra|bytes|其他数据
    """

    code: str = peewee.CharField(max_length=64,index=True)
    yy_mm_dd: int = peewee.IntegerField(index=True)
    hh_mm: int = peewee.IntegerField(index=True)
    source:int = peewee.SmallIntegerField(null=True)
    market:int = peewee.SmallIntegerField(null=True)
    group:int = peewee.SmallIntegerField(index=True)
    time:datetime = peewee.TimestampField(null=True)
    close: float = peewee.FloatField(null=True)
    open: float = peewee.FloatField(null=True)
    high: float = peewee.FloatField(null=True)
    low: float = peewee.FloatField(null=True)
    pre_close: float = peewee.FloatField(null=True)
    volume:int = peewee.BigIntegerField(null=True)
    amount: float = peewee.DoubleField(null=True)
    level_data: bytes = peewee.BlobField(null=True)
    extra: bytes = peewee.BlobField(null=True)

    def __str__(self):
        return f"{self.__class__.__name__}[code:{self.code},source:{self.source}" \
                f",yy_mm_dd:{self.yy_mm_dd}" \
                f",hh_mm:{self.hh_mm}" \
               f",close:{self.close}" \
               f",open:{self.open}" \
               f",high:{self.high}" \
               f",low:{self.low}" \
               f",pre_close:{self.pre_close}" \
               f",volume:{self.volume}" \
               f",amount:{self.amount}" \
               f"]"

class TodayTickShotModel(TickShotModel):
    """
    今日最新TickSHotModel。
    与TickShotModel不同的是，有唯一值： code+yy_mm_dd
    """

    def update_tick_value(self,tick:TickShotModel):
        """
        除了group，code，yy_mm_dd,其他值都拷贝
        :param tick:
        :return:
        """
        self.source = tick.source
        self.market = tick.market
        self.hh_mm = tick.hh_mm
        self.time = tick.time
        self.close = tick.close
        self.open = tick.open
        self.high = tick.high
        self.low = tick.low
        self.pre_close = tick.pre_close
        self.volume = tick.volume
        self.amount = tick.amount
        self.level_data = tick.level_data
        self.extra = tick.extra

    def clone(self):
        new_tick = TodayTickShotModel()
        new_tick.code = self.code
        new_tick.group = self.group
        new_tick.yy_mm_dd = self.yy_mm_dd
        new_tick.update_tick_value(self)
        return new_tick